# Arun & Bill

require "rexml/document"
include REXML

class Journal

  attr_reader :owner
  attr_reader :trips
  attr_reader :document
  def initialize(document, trip=nil, newfilename=nil)
    if document.is_a? Document
      @document = document
      @owner = Owner.new(@document.root.get_elements("owner").first)
      if(@document.root.elements["trip"]!=nil)
      @trips=[]
      @document.root.elements.each("trip") { |tripElement| @trips.push(Trip.new(tripElement)) }
      end
    elsif document.is_a? String
      @document = Document.new(File.new(document))
      @owner = Owner.new(@document.root.get_elements("owner").first)
      if(@document.root.elements["trip"]!=nil)
      @trips=[]
      @document.root.elements.each("trip") { |tripElement| @trips.push(Trip.new(tripElement)) }
      end
    elsif document.is_a? Owner
      my_file = File.new(newfilename, 'w+')
      my_file.puts "<journal>\n</journal>"
      my_file.close
      @document = Document.new(File.new(newfilename))
      @document.root.add_element document.ownerElement
      @owner = document
      @document.root.insert_after("//owner", trip.tripElement)
      @trips = []
      @trips.push(trip)
    end
    return @document
  end

  def add element
    if element.is_a? Owner
      @document.root.elements["owner"]=element.ownerElement
      @owner = element
    elsif element.is_a? Trip
      @document.root.add_element element.tripElement
      @trips.push(element)
    else
      raise "Unacceptable parameter: " + element.to_s
    end
  end
	
  def delete element
    if element.is_a? Trip
      @document.root.delete_element element.tripElement
      @trips.delete element
    else
      raise "Unacceptable parameter: " + element.to_s
    end
  end
  
  def owner= owner
    raise "Unacceptable parameter: " + element.to_s if !owner.is_a? Owner
    @owner.ownerElement=element.ownerElement;
  end

  def to_s
      @document.root.to_s
  end
  
  def WriteToFile filename
    myFile = File.new(filename, 'w')
    myFile.puts @document.root
    myFile.close
  end

end

class Owner
  attr_reader :ownerElement, :name
  def initialize (ownerElement)
    if (ownerElement.is_a? Element)  && (ownerElement.elements["name"] != nil)
      @ownerElement = ownerElement
      @name = Name.new(ownerElement.elements["name"])
    else
      @ownerElement = Element.new("owner")
      @ownerElement.add_element ownerElement.nameElement
      if ownerElement.is_a? Name
       	 @name = ownerElement
      else
        @name = Name.new(ownerElement.to_s)  
      end
    end
  end
  
  def name= name
    @name.nameElement.text = name.to_s
  end
  
  def getName
    return @name.nameElement.text
  end
  
  def getOwner
    return @name.nameElement.text
  end
  
  def add element
    if (element.is_a? Name)
      @name.nameElement = element.nameElement
      @name = element
    else
      raise "Unacceptable parameter: " + element.to_s
    end
  end 
end


class Name
  attr_reader :nameElement
  def initialize(nameElement)
    if nameElement.is_a? Element
      @nameElement = nameElement
    else
      @nameElement = Element.new("name")
      @nameElement.text = nameElement.to_s
    end
  end
end


class Trip
  attr_reader :tripElement
  attr_reader :name
  attr_reader :tripstartdate
  attr_reader :tripenddate
  attr_reader :destinations
  def initialize (tripElement, tripStartDate = nil, tripEndDate = nil, destination=nil)
    if tripElement.is_a? Element
      @tripElement = tripElement
      @name = Name.new(tripElement.elements["name"])
      @tripstartdate = TripStartDate.new(tripElement.elements["tripstartdate"])
      @tripenddate = TripEndDate.new(tripElement.elements["tripenddate"])
      @destinations = []
      @tripElement.elements.each("destination") {|destinationElement| @destinations.push(Destination.new(destinationElement))}
    elsif tripElement.is_a? Name
      @tripElement = Element.new("trip")
      @tripElement.add_element tripElement.nameElement
      @name = tripElement
      @tripElement.insert_after("//name", tripStartDate.tripstartdateElement)
      @tripstartdate = tripStartDate
      @tripElement.insert_after("//tripstartdate", tripEndDate.tripenddateElement)
      @tripenddate = tripEndDate
      @tripElement.insert_after("//tripenddate", destination.destinationElement)
      @destinations = [destination]
    end
  end
  
  def getTripEndDate
    return @tripElement.get_elements("tripenddate").first.text
  end
  
  def tripenddate= date
    @tripenddate = TripEndDate.new(date)
    @tripElement.elements["tripenddate"] = @tripenddate.tripenddateElement.to_s
  end

  def getTripStartDate
    return @tripElement.get_elements("tripstartdate").first.text
  end
  
  def tripstartdate= date
     @tripstartdate = TripStartDate.new(date)
     @tripElement.elements["tripstartdate"] = @tripstartdate.tripstartdateElement.to_s
  end

  def getName
    @tripElement.get_elements("name").first.text
  end
  
  def name= nameToUse
    @name = Name.new(nameToUse)
    @tripElement.elements["name"] = @name.nameElement.to_s
  end
  

  def add(element, destinationToInsertAfter = nil)
    if element.is_a? Name
      @name.nameElement= element.nameElement
      @name = element
    elsif element.is_a? TripStartDate
      @tripstartdate.tripstartdateElement = element.tripstartdateElement
      @tripstartdate = element
    elsif element.is_a? TripEndDate
      @tripenddate.tripenddateElement = element.tripenddateElement

    elsif element.is_a? Destination
      if destinationToInsertAfter.is_a? Destination 
        @tripElement.insert_after(destinationToInsertAfter.destinationElement,element.destinationElement)
        @destinations.insert(@destinations.index(destinationToInsertAfter) + 1, destinationToInsertAfter)
      else
        @tripElement.add_element element.destinationElement
        @destinations.push(element)
      end 
    else
      raise "Unacceptable parameter: " + element.to_s
    end
  end
  
  def delete element
    if element.is_a? Destination
      @tripElement.delete_element element.destinationElement
      @destinations.delete Destination
    else
      raise "Unacceptable parameter: " + element.to_s
    end
  end
end


class TripStartDate
  attr_reader :tripstartdateElement
  def initialize (tripstartdateElement)
    if (tripstartdateElement.is_a? Element)
      @tripstartdateElement = tripstartdateElement
    else
      @tripstartdateElement = Element.new("tripstartdate")
      @tripstartdateElement.text = tripstartdateElement.to_s
    end 
  end
end


class TripEndDate
  attr_reader :tripenddateElement
  def initialize (tripenddateElement)
    if (tripenddateElement.is_a? Element)
      @tripenddateElement = tripenddateElement
    else
      @tripenddateElement = Element.new("tripenddate")
      @tripenddateElement.text = tripenddateElement.to_s
    end 
  end
end


class Destination
  attr_reader :destinationElement
  attr_reader :name
  attr_reader :city
  attr_reader :country
  attr_reader :deststartdate
  attr_reader :destenddate
  attr_reader :photos
  attr_reader :entries
  def initialize (destinationElement, city=nil, country=nil, deststartdate=nil, destenddate=nil, photoOrentry=nil)
    if (destinationElement.is_a? Element)
      @destinationElement = destinationElement
      @name = Name.new(destinationElement.elements["name"])
      if(destinationElement.elements["city"]!=nil)
        @city = City.new(destinationElement.elements["city"])
      else
        @city = nil
      end
      if(destinationElement.elements["country"]!=nil)
        @country = Country.new(destinationElement.elements["country"])
      else
        @country = nil
      end
      @deststartdate = DestStartDate.new(destinationElement.elements["deststartdate"])
      @destenddate = DestEndDate.new(destinationElement.elements["destenddate"])
      @entries = []
      @photos = []
      if((destinationElement.elements["photo"]!=nil || destinationElement.elements["entry"]!=nil) && !(destinationElement.elements["photo"]!=nil && destinationElement.elements["entry"]!=nil))
        @destinationElement.elements.each {|element| 
                  if element.name == "photo"
                    @photos.push(Photo.new(element))
                  elsif element.name == "entry"
                    @entries.push(Entry.new(element))
                  end
					  }
      end
    elsif(destinationElement.is_a? Name)
      @destinationElement = Element.new("destination")
      @destinationElement.add_element destinationElement.nameElement
      @name = destinationElement
      if(city!=nil)
        @destinationElement.insert_after("//name", city.cityElement)
        @city = city
      end
      if(country!=nil)
        if(city !=nil)
          @destinationElement.insert_after("//city", country.countryElement)
        elsif(city==nil)
          @destinationElement.insert_after("//name", country.countryElement)
        end
        @country = country
      end
      if(country!=nil)
        @destinationElement.insert_after("//country", deststartdate.deststartdateElement)
      elsif(country==nil)
        if(city==nil)
          @destinationElement.insert_after("//name", deststartdate.deststartdateElement)
        elsif(city!=nil)
          @destinationElement.insert_after("//city", deststartdate.deststartdateElement)
        end
      end
      @deststartdate = deststartdate
      @destinationElement.insert_after("//deststartdate", destenddate.destenddateElement)
      @destenddate = destenddate
      @photos = []
      @entries = []
      if(photoOrentry.is_a? Photo)
        @destinationElement.insert_after("//destenddate", photoOrentry.photoElement)
        @photos.push photoOrentry
      elsif(photoOrentry.is_a? Entry)
        @destinationElement.insert_after("//destenddate", photoOrentry.entryElement)
        @entries.push photoOrentry
      end
    end
  end
    
    def getCountry
      if(country!="")
        return @country.countryElement.text
      else
        raise "There is no 'country' element!"
      end
    end
    
    def getCity
      if(city!="")
        return @city.cityElement.text
      else
        raise "There is no 'city' element!"
      end
    end
    
    def getName
      return @name.nameElement.text
    end
    
    def getDestStartDate
      return @deststartdate.deststartdateElement.text
    end
    
    def getDestEndDate
      return @destenddate.destenddateElement.text
    end
    
    def name= name
      @name.nameElement.text = name.to_s
    end
    
    def deststartdate= deststartdate
      @deststartdate.deststartdateElement.text = deststartdate.to_s
    end
    
    def destenddate= destenddate
      @destenddate.destenddateElement.text = destenddate.to_s
    end
    
    def city= city
      @city.cityElement.text = city.to_s
    end
    
    def country= country
      @country.countryElement.text = country.to_s
    end
    
    def add (element, destinationToInsertAfter=nil)
      if  element.is_a? Name
        @destinationElement.elements["name"] = element.nameElement
        @name = element
      elsif element.is_a? City
        @destinationElement.elements["city"] = element.cityElement
        @city = element
      elsif element.is_a? Country
        @destinationElement.elements["country"] = element.countryElement
        @country = element
      elsif element.is_a? DestStartDate
        @destinationElement.elements["deststartdate"] = element.deststartdateElement
        @deststartdate = element
      elsif element.is_a? DestEndDate
        @destinationElement.elements["destenddate"] = element.destenddateElement
        @destenddate = element
      elsif (element.is_a? Photo)
        if(destinationToInsertAfter.is_a? Photo)
          @destinationElement.insert_after(destinationToInsertAfter.photoElement, element.photoElement)
        elsif(destinationToInsertAfter.is_a? Entry)
          @destinationElement.insert_after(destinationToInsertAfter.entryElement, element.photoElement)
        else
          @destinationElement.add(element.photoElement)
        end
        @photos = []
        @destinationElement.elements.each { |photoElement| @photos.push(Photo.new(photoElement)) if (photoElement.name == "photo")}
      elsif (element.is_a? Entry)
        if(destinationToInsertAfter.is_a? Entry)
          @destinationElement.insert_after(destinationToInsertAfter.entryElement, element.entryElement)
        elsif(destinationToInsertAfter.is_a? Photo)
          @destinationElement.insert_after(destinationToInsertAfter.photoElement, element.entryElement)
        else
          @destinationElement.add(element.entryElement)
        end
        @entries = []
        @destinationElement.elements.each { |entryElement| @entries.push(Entry.new(entryElement)) if(entryElement.name == "entry") }
      else      
        raise "Unacceptable parameter: " + element.to_s
      end
  end
  
	def delete element
		if element.is_a? Entry
			@destinationElement.delete_element element.entryElement
      @entries.delete element
		elsif element.is_a? Photo
			@destinationElement.delete_element element.photoElement
      @photos.delete element
		else
			raise "Unacceptable parameter: " + element.to_s
		end
	end
end


class City
  attr_reader :cityElement
  def initialize(cityElement)
    if cityElement.is_a? Element
      @cityElement = cityElement
    else
      @cityElement = Element.new("city")
      @cityElement.text = cityElement.to_s
    end
  end
end


class Country
  attr_reader :countryElement
  def initialize(countryElement)
    if countryElement.is_a? Element
      @countryElement = countryElement
    else
      @countryElement = Element.new("country")
      @countryElement.text = countryElement.to_s
    end
  end
end


class DestStartDate
  attr_reader :deststartdateElement
  def initialize(deststartdateElement)
    if deststartdateElement.is_a? Element
      @deststartdateElement = deststartdateElement
    else
      @deststartdateElement = Element.new("deststartdate")
      @deststartdateElement.text = deststartdateElement.to_s
    end
  end
end



class DestEndDate
  attr_reader :destenddateElement
  def initialize(destenddateElement)
    if destenddateElement.is_a? Element
      @destenddateElement = destenddateElement
    else
      @destenddateElement = Element.new("destenddate")
      @destenddateElement.text = destenddateElement.to_s
    end
  end
end


class Photo
  attr_reader :photoElement
  attr_reader :id
  attr_reader :url
  attr_reader :comment
  attr_reader :datetaken
  def initialize (photoElement, url=nil, comment=nil, datetaken=nil)
    if photoElement.is_a? Element
      @photoElement = photoElement
      @id = Id.new(photoElement.elements["id"])
      @url = Url.new(photoElement.elements["url"])
      @comment = Comment.new(photoElement.elements["comment"])
      @datetaken = DateTaken.new(photoElement.elements["datetaken"])
    elsif(photoElement.is_a? Id)
        @photoElement = Element.new("photo")
        @photoElement.add_element photoElement.idElement
        @id = photoElement
        @photoElement.insert_after("//id", url.urlElement)
        @url = url
        @photoElement.insert_after("//url", comment.commentElement)
        @comment = comment
        @photoElement.insert_after("//comment", datetaken.datetakenElement)
        @datetaken = datetaken
    end
  end
  
  def getId
    return @id.idElement.text
  end 
  
  def getUrl
    return @url.urlElement.text
  end
  
  def getComment
    return @comment.commentElement.text
  end
  
  def getDateTaken
    return @datetaken.datetakenElement.text
  end
  
  def id= id
    @id.idElement.text = id
  end
  
  def url= url
    @url.urlElement.text = url
  end
  
  def comment= comment
    @comment.commentElement.text = comment
  end
  
  def datetaken= datetaken
    @datetaken.datetakenElement.text = datetaken
  end
  
  def add element
    if (element.is_a? Id)
      @photoElement.elements["id"] = element.idElement
      @id = element
    elsif (element.is_a? Url)
      @photoElement.elements["url"] = element.urlElement
      @url = element
    elsif (element.is_a? Comment)
      @photoElement.elements["comment"] = element.commentElement
      @comment = element
    elsif (element.is_a? DateTaken)
      @photoElement.elements["datetaken"] = element.datetakenElement
      @datetaken = element
    else
      raise "Unacceptable parameter: " + element.to_s
    end
  end
end


class Entry
  attr_reader :entryElement
  attr_reader :title
  attr_reader :entrytime
  attr_reader :htext
  def initialize (entryElement, entrytime=nil, htext=nil)
    if (entryElement.is_a? Element)
      @entryElement = entryElement
      @title = Title.new(entryElement.elements["title"])
      @entrytime = EntryTime.new(entryElement.elements["entrytime"])
      @htext = Htext.new(entryElement.elements["htext"])
    elsif(entryElement.is_a? Title)
        @entryElement = Element.new("entry")
        @entryElement.add_element entryElement.titleElement
        @title = entryElement
        @entryElement.insert_after("//title", entrytime.entrytimeElement)
        @entrytime = entrytime
        @entryElement.insert_after("//entrytime", htext.htextElement)
        @htext = htext
    end
  end
  
  def getTitle
    return @title.titleElement.text
  end
  
  def getEntryTime
    return @entrytime.entrytimeElement.text
  end
  
  def getHtext
    return @htext.htextElement.text
  end
  
  def title= title
    @title.titleElement.text = title
  end
  
  def entrytime= entrytime
    @entrytime.entrytimeElement.text = entrytime
  end
  
  def htext= htext
    @htext.htextElement.text = htext
  end
  
  def add element
    if (element.is_a? Title)
      @entryElement.elements["title"] = element.titleElement
      @title = element
    elsif (element.is_a? EntryTime)
      @entryElement.elements["entrytime"] = element.entrytimeElement
      @entrytime = element
    elsif (element.is_a? Htext)
      @entryElement.elements["htext"] = element.htextElement
      @htext = element
    else
      raise "Unacceptable parameter: " + element.to_s
    end
  end
end

class Id
  attr_reader :idElement
  def initialize(idElement)
    if idElement.is_a? Element
      @idElement = idElement
    else
      @idElement = Element.new("id")
      @idElement.text = idElement.to_s
    end
  end
end


class Url
  attr_reader :urlElement
  def initialize(urlElement)
    if urlElement.is_a? Element
      @urlElement = urlElement
    else
      @urlElement = Element.new("url")
      @urlElement.text = urlElement.to_s
    end
  end
end


class Comment
  attr_reader :commentElement
  def initialize(commentElement)
    if commentElement.is_a? Element
      @commentElement = commentElement
    else
      @commentElement = Element.new("comment")
      @commentElement.text = commentElement.to_s
    end
  end
end


class DateTaken
  attr_reader :datetakenElement
  def initialize(datetakenElement)
    if datetakenElement.is_a? Element
      @datetakenElement = datetakenElement
    else
      @datetakenElement = Element.new("datetaken")
      @datetakenElement.text = datetakenElement.to_s
    end
  end
end


class Title
  attr_reader :titleElement
  def initialize(titleElement)
    if titleElement.is_a? Element
      @titleElement = titleElement
    else
      @titleElement = Element.new("title")
      @titleElement.text = titleElement.to_s
    end
  end
end


class EntryTime
  attr_reader :entrytimeElement
  def initialize(entrytimeElement)
    if entrytimeElement.is_a? Element
      @entrytimeElement = entrytimeElement
    else
      @entrytimeElement = Element.new("entrytime")
      @entrytimeElement.text = entrytimeElement.to_s
    end
  end
end


class Htext
  attr_reader :htextElement
  def initialize(htextElement)
    if htextElement.is_a? Element
      @htextElement = htextElement
    else
      @htextElement = Element.new("htext")
      @htextElement.text = htextElement.to_s
    end
  end
end



